package com.jah.picavue.client.view;

import java.util.ArrayList;

import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.logical.shared.ResizeEvent;
import com.google.gwt.event.logical.shared.ResizeHandler;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.DockPanel;
import com.google.gwt.user.client.ui.Grid;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HasHorizontalAlignment;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Hyperlink;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.RootPanel;
import com.jah.picavue.client.Config;
import com.jah.picavue.client.EventBus;
import com.jah.picavue.client.events.CancelTimerEvent;
import com.jah.picavue.client.events.StartTimerEvent;
import com.jah.picavue.client.model.Album;
import com.jah.picavue.client.model.Photo;

@SuppressWarnings("unchecked")
public class AlbumView implements ResizeHandler, StartTimerEvent.Handler, CancelTimerEvent.Handler {

	// private Album album;
	private String view;
	private String albumID;
	private ArrayList<Photo> photos;
	private ArrayList<Thumbnail> thumbs = new ArrayList();

	private int cursor = 0;
	private int displayed_first = 0;
/*	private int displayed_last = 0; */
	private Image ssVisibleImage = new Image();
	private Image ssHiddenImage = new Image();

	private RootPanel rootPanel= RootPanel.get(Config.ROOTPANELID);
	private DockPanel dock = new DockPanel();
	private Grid grid = new Grid();
	private int clientWidth;
	private int clientHeight;
	private String styleWidth;
	private String styleHeight;
	
	private Timer timer;
	private boolean ss_isrunning = true;

	public AlbumView(Album album, String view) {
		this.view = view;
		this.photos = album.getPhotos();
		this.albumID = album.getID();

		// Generate Thumbnails
		for (int i = 0; i<photos.size(); i++) {
			Photo p = photos.get(i);
			Thumbnail thumb = new Thumbnail(p.getID(), p.getThumb(), p.getCaption(), view);
			thumb.setPhoto(p);
			thumbs.add(thumb);
		}
        Window.addResizeHandler(this);
        EventBus.get().addHandler(StartTimerEvent.TYPE, this);
        EventBus.get().addHandler(CancelTimerEvent.TYPE, this);
		redraw(view);
	}

	private void doSlideShow() {
		if (cursor >= photos.size()) cursor = 0;
		view = "slideshow";
		dock.clear();
		Photo photoData = photos.get(cursor);
		ssVisibleImage.setUrl(photoData.getContent());
		int cplusone = cursor+1;
		if (cplusone >= photos.size()) {
			cplusone = 0;
		}
		ssHiddenImage.setUrl(photos.get(cplusone).getContent());
		displayed_first = cursor;
		
		photoData.resetDims();
		int left;
		int top;
		while (true) {
			left = ((Window.getClientWidth() - photoData.getWidth().intValue()) / 2) -35;
			top = ((Window.getClientHeight() - photoData.getHeight().intValue()) / 2) -35;
			int new_width = 0;
			int new_height = 0;
			if (left < 0){
				// image is wider than window - scale it.
				new_width = (2*left) + photoData.getWidth().intValue() - 30; // 30px less than the window
				new_height = (int)((new_width) * (photoData.getHeight() / photoData.getWidth()));
				if (left < 0 && new_height > (Window.getClientHeight() - 30)) {
					// scaled image is even now too tall
					new_height = Window.getClientHeight() - 30;
					new_width = (int)((new_height) * (photoData.getWidth() / photoData.getHeight()));
				}
			}
			if (new_height == 0 && top < 0){
				// image has not been modded yet, but it is too tall - scale it.
				new_height = (2*top) + photoData.getHeight().intValue() -30; // 20px less than the window
				new_width = (int)((new_height) * (photoData.getWidth() / photoData.getHeight()));
				if ( new_width > (Window.getClientWidth() - 30)) {
					// scaled image is even now too wide
					new_width = Window.getClientWidth() - 30;
					new_height = (int)((new_width) * (photoData.getHeight() / photoData.getWidth()));
				}
			}
			if (new_height != 0 && new_width != 0) {
				photoData.setWidth((double) new_width);
				photoData.setHeight((double) new_height);

				continue; // recalculate left and top based on the new image size
			}
			// OK all's well.
			ssVisibleImage.setSize(photoData.getWidth().toString(), photoData.getHeight().toString());
			break;
		}
		
		// TopNav
		HorizontalPanel topNav = new HorizontalPanel();
		dock.add(topNav, DockPanel.NORTH);
		topNav.setWidth("100%");
		Hyperlink homeLink = new Hyperlink( "<< Show Albums", "index" );
		Hyperlink sshowLink = new Hyperlink( "View Gallery", "gallery+" + this.albumID );
		topNav.add(homeLink);
		topNav.add(sshowLink);
		topNav.setHeight("30px");
		topNav.setCellWidth(homeLink, "50%");
		topNav.setCellHorizontalAlignment(homeLink, HasHorizontalAlignment.ALIGN_CENTER);
		topNav.setCellWidth(sshowLink, "50%");
		topNav.setCellHorizontalAlignment(sshowLink, HasHorizontalAlignment.ALIGN_CENTER);
		
		
		//bottom navigation Start Stop link
		DockPanel bottomNav = new DockPanel();
		dock.add(bottomNav, DockPanel.SOUTH);
		bottomNav.setWidth("100%");
		HTML pause_play = new HTML("<a href=\"javascript:undefined;\">Play</a>");
		bottomNav.add(pause_play, DockPanel.CENTER);
		pause_play.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_CENTER);
		pause_play.addClickHandler(new ClickHandler() {
			public void onClick(ClickEvent event) {
				HTML h = (HTML) event.getSource();
				if (ss_isrunning) {
					h.setHTML("<a href=\"javascript:undefined;\">Play</a>");
					EventBus.get().fireEvent(new CancelTimerEvent());
				} else {
					h.setHTML("<a href=\"javascript:undefined;\">Pause</a>");
					EventBus.get().fireEvent(new StartTimerEvent());
				}
			}
		});
		
		
		dock.add(ssHiddenImage, DockPanel.SOUTH);
		ssHiddenImage.setVisible(false);
		dock.add(ssVisibleImage, DockPanel.CENTER);
		
		rootPanel.clear();
		rootPanel.add(dock);
		rootPanel.setWidgetPosition(dock, left, top);
		
		if (ss_isrunning) {
			pause_play.setHTML("<a href=\"javascript:undefined;\">Pause</a>");
			EventBus.get().fireEvent(new StartTimerEvent());
		}

	}

	private void doGallery() {

		cursor = 0;

		calcSpace();
		styleWidth = (new Integer(clientWidth)).toString() + "px";
		styleHeight = (new Integer(clientHeight)).toString() + "px";

		rootPanel.clear();
		grid.clear();
		dock.clear();

		dock.setWidth(styleWidth);
		dock.setHeight(styleHeight);

		// show all widget
		HorizontalPanel topNav = new HorizontalPanel();
		dock.add(topNav, DockPanel.NORTH);
		topNav.setWidth("100%");
		Hyperlink homeLink = new Hyperlink( "<< Show Albums", "index" );
		Hyperlink sshowLink = new Hyperlink( "View as Slide Show", "slideshow+" + this.albumID );
		topNav.add(homeLink);
		topNav.add(sshowLink);
		topNav.setHeight("30px");
		topNav.setCellWidth(homeLink, "33%");
		topNav.setCellHorizontalAlignment(homeLink, HasHorizontalAlignment.ALIGN_CENTER);
		topNav.setCellWidth(sshowLink, "33%");
		topNav.setCellHorizontalAlignment(sshowLink, HasHorizontalAlignment.ALIGN_CENTER);

		// TODO This is a bit dirty, not very accurate and needs drastic improvement!!
		setGridSize(clientWidth, clientHeight - 60, thumbs.get(0).getWidth(),
				thumbs.get(0).getHeight(), (double) 20);

		// do the grid -
		final int rows = grid.getRowCount();
		final int cols = grid.getColumnCount();
		displayed_first = this.cursor;
		if (thumbs.size() < 1) return;
		grid.setCellSpacing(20);
		for (int row = 0; row < rows; row++) {
			for (int col = 0; col < cols; col++) {
				if (this.cursor == thumbs.size()) {
					row = rows;
					col = cols;
					continue;
				}
				grid.setWidget(row, col, thumbs.get(this.cursor));
				this.cursor++;  /* !! Note well that cursor increments past thumbs last index !! */
			}
		}

		cursor = 0;
		dock.add(grid, DockPanel.CENTER);

		rootPanel.add(dock);
	}

	private void setGridSize(int gw, int gh, double tw, double th, double margin) {
		int rows = 0;
		int cols = (int) (gw / (tw+margin+2)); // 1px padding-left/right
		int thumbs_count = thumbs.size();
		rows = ((thumbs_count % cols == 0) ? thumbs_count/cols : 1 + (int) thumbs_count/cols);
		if (rows < 1) rows = 1;
		if (cols < 1) cols = 1;
		grid.resize(rows,cols);
	}

	private void calcSpace() {
		int left = rootPanel.getAbsoluteLeft();
		int top = rootPanel.getAbsoluteTop();
		clientWidth = Window.getClientWidth() - (2* left) -20;
		clientHeight = Window.getClientHeight() - (top + 50);
	}

	public void setCursor(int index) {
		this.cursor = index;
	}

	public void redraw(String view) {
		this.view = view;
		if (view.equals("gallery")) {
			doGallery();
		} else {
			//this.cursor = displayed_first;
			doSlideShow();
		}
	}
	
	public String getAlbumID() {
		return this.albumID;
	}
	
	public void onResize(ResizeEvent event) {
		this.cursor = this.displayed_first;
		if (this.view.equals("gallery")) {
			doGallery();
		} else {
			doSlideShow();
		}
	}
	
	public void onCancelTimerRequest(CancelTimerEvent event) {
		if (this.timer != null) {
			this.timer.cancel();
		}
		this.ss_isrunning = false;
	}
	
	public void onStartTimerRequest(StartTimerEvent event) {
		if (this.timer == null) {
			this.timer = new Timer() {
				@Override
				public void run() {
					if (cursor >= photos.size()) {
						cursor = 0;
					} else {
						cursor++;
					}
					doSlideShow();
				}
		    };
		}
	    this.timer.scheduleRepeating(event.getPeriod());
		this.ss_isrunning = true;
	}
	
	public void setSlideShowStart() {
		this.cursor = this.displayed_first;
	}
}
